//定义：以动态地给某个对象添加一些额外的职责 而不影响从这个类中派生的其他对象 急用即付的方式 能够在不改变对象自身的基础上 在程序运行期间给对象动态的添加职责

//核心：是为对象动态添加行为 经过多层包装 可以形成一条装饰连

//实现：最简单的装饰者  是重写对象的属性 
//可以使用传统面向对象的方法来实现装饰，添加技能
function Person() {}

Person.prototype.skill = function() {
    console.log('数学');
};

// 装饰器，还会音乐
function MusicDecorator(person) {
    this.person = person;
}

MusicDecorator.prototype.skill = function() {
    this.person.skill();
    console.log('音乐');
};

// 装饰器，还会跑步
function RunDecorator(person) {
    this.person = person;
}

RunDecorator.prototype.skill = function() {
    this.person.skill();
    console.log('跑步');
};

var person = new Person();

// 装饰一下
var person1 = new MusicDecorator(person);
person1 = new RunDecorator(person1);

person.skill(); // 数学
person1.skill(); // 数学 音乐 跑步

//JS中 函数作为一等对象 所以我们也可以使用更通用的装饰函数

//装饰器 在当前函数执行前先执行另一个函数

function decoratorBefore(fn,beforeFn){
    return function(){
        var ret = beforeFn.apply(this,arguments);

        //在前一个函数中判断 需不需要执行当前函数
        if(ret !== false){
            fn.apply(this,arguments)
        }
    }
}
function skill() {
    console.log('1数学');
}

function skillMusic() {
    console.log('1音乐');
}

function skillRun() {
    console.log('1跑步');
}

var skillDecorator = decoratorBefore(skill, skillMusic);
skillDecorator = decoratorBefore(skillDecorator, skillRun);

skillDecorator(); // 跑步 音乐 数学